﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;

namespace loginSQL.Util
{
    public class BookCollection
    {
        List<String> filenameList;
        List<String> defaultList;
        List<BookData> bookdata;
        Dictionary<String, String> licenseDic;

        public List<String> FilenameList
        {
            get
            {
                return filenameList;
            }
        }

        public List<BookData> BookList
        {
            get
            {
                return bookdata;
            }
        }

        public BookCollection()
        {
            filenameList = new List<string>();
            bookdata = new List<BookData>();
            defaultList = new List<string>();
            licenseDic = new Dictionary<string, string>();
        }

        public void Save(String filename)
        {
            XmlWriterSettings settings=new XmlWriterSettings();
            settings.Indent=true;
            settings.IndentChars="\t";
            using (XmlWriter xw = XmlWriter.Create(filename, settings))
            {
                xw.WriteStartDocument();
                xw.WriteStartElement("collections");
                foreach (String path in defaultList)
                {
                    xw.WriteStartElement("path");
                    xw.WriteAttributeString("type", "default");
                    xw.WriteString(path);
                    xw.WriteEndElement();
                }
                foreach (String path in filenameList)
                {
                    xw.WriteStartElement("path");
                    xw.WriteAttributeString("type", "current");
                    xw.WriteString(path);
                    xw.WriteEndElement();
                }
                xw.WriteEndElement();
            }
        }

        public static BookCollection Load(String filename)
        {
            BookCollection collection = null;
            using (XmlReader xr = XmlReader.Create(filename))
            {
                collection = new BookCollection();
                xr.ReadToFollowing("collections");
                while (xr.Read())
                {
                    switch (xr.NodeType)
                    {
                        case XmlNodeType.Element:
                            if (xr.Name.Equals("path", StringComparison.OrdinalIgnoreCase))
                            {
                                string type=xr.GetAttribute("type");
                                xr.Read();
                                String val = xr.Value.Trim();
                                if (File.Exists(val))
                                {
                                    if (type.Equals("default", StringComparison.OrdinalIgnoreCase))
                                    {
                                        collection.defaultList.Add(val);
                                    }
                                    else if (type.Equals("current", StringComparison.OrdinalIgnoreCase))
                                    {
                                        collection.filenameList.Add(val);
                                    }
                                }
                            }
                            break;
                    }
                }
                foreach (String path in collection.defaultList)
                {
                    BookData cur=BookData.Load(path);
                    collection.bookdata.Add(cur);
                    collection.licenseDic.Add(cur.Name, path);
                }
                foreach (String path in collection.filenameList)
                {
                    BookData cur = BookData.Load(path);
                    BookData def = collection.GetBook(cur.Name);
                    collection.bookdata.Remove(def);
                    collection.bookdata.Add(cur);
                    collection.licenseDic[cur.Name] = path;
                }
            }
            return collection;
        }

        public List<String> BookName
        {
            get
            {
                List<String> list = new List<String>();
                foreach (BookData data in bookdata)
                {
                    list.Add(data.Name);
                }
                return list;
            }
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("{");
            foreach (BookData book in bookdata)
            {
                sb.Append(book.Name).Append(", ");
            }
            sb.Remove(sb.Length - 2,2);
            sb.Append("}");
            return sb.ToString();
        }

        public void SaveBook(int curBookIndex)
        {
            bookdata[curBookIndex].Save(filenameList[curBookIndex]);
        }

        public PageData GetPageData(int curBookIndex, int curPageIndex)
        {
            return bookdata[curBookIndex].PageData[curPageIndex];
        }

        public int GetPageCount(int curBookIndex)
        {
            return bookdata[curBookIndex].PageCount;
        }

        public void SetPageData(int curBookIndex, int curPageIndex, string attribute, System.Drawing.PointF pointF, bool vis)
        {
            bookdata[curBookIndex].PageData[curPageIndex].SetData(attribute, pointF, vis);
        }

        public void SetBookFilename(int curBookIndex, string filename)
        {
            filenameList[curBookIndex] = filename;
        }

        public void AddNewBook(string path)
        {
            // cek file ada ga
            if (File.Exists(path))
            {
                BookData book = BookData.Load(path);
                // cek buku unik ga lisensinya
                if (licenseDic.ContainsKey(book.Name)==false)
                {
                    bookdata.Add(book);
                    defaultList.Add(path);
                    filenameList.Add(path);
                    licenseDic.Add(book.Name, path);
                }
                else
                {
                    throw new ArgumentException("Default book exist", path);
                }
            }
        }

        public void UpdateBookPath(string path)
        {
            BookData book = BookData.Load(path);
            if (licenseDic.ContainsKey(book.Name))
            {
                string curpath = licenseDic[book.Name];
                filenameList.Remove(curpath);
                filenameList.Add(path);
                licenseDic[book.Name] = path;
                BookData cur = GetBook(book.Name);
                bookdata.Remove(cur);
                bookdata.Add(book);
            }
            else
            {
                throw new ArgumentException("No book to update.", path);
            }
        }

        public void RemoveBook(string licenseName)
        {
            // cari semua buku dengan lisensi yang sama
            // kalo ga ada ya ga usah diapa-apain...
            if (licenseDic.ContainsKey(licenseName))
            {
                BookData book = GetBook(licenseName);
                bookdata.Remove(book);
                filenameList.Remove(licenseDic[licenseName]);
                for (int i = 0; i < defaultList.Count; i++)
                {
                    BookData cur = BookData.Load(defaultList[i]);
                    if (book.Name.Equals(cur.Name, StringComparison.OrdinalIgnoreCase))
                    {
                        defaultList.RemoveAt(i);
                        break;
                    }
                }
                licenseDic.Remove(licenseName);
            }
        }

        public void AddNewPage(int bookIndex)
        {
            bookdata[bookIndex].AddNewPage();
        }

        public void DeletePage(int curBookIndex, int curPageIndex)
        {
            bookdata[curBookIndex].PageData.RemoveAt(curPageIndex);
        }

        public BookData GetBook(string licenseName)
        {
            foreach (BookData book in bookdata)
            {
                if (licenseName.Equals(book.Name, StringComparison.OrdinalIgnoreCase))
                {
                    return book;
                }
            }
            return null;
        }

        public void RemoveBook(BookData book)
        {
            for(int i=0;i<bookdata.Count;i++)
            {
                if (book.Name.Equals(bookdata[i].Name))
                {
                    bookdata.RemoveAt(i);
                    filenameList.RemoveAt(i);
                }
            }
        }

        public string GetDefaultBookFilename(string licenseName)
        {
            if (licenseDic.ContainsKey(licenseName))
            {
                BookData book = GetBook(licenseName);
                for (int i = 0; i < defaultList.Count; i++)
                {
                    BookData cur = BookData.Load(defaultList[i]);
                    if (book.Name.Equals(cur.Name, StringComparison.OrdinalIgnoreCase))
                    {
                        return defaultList[i];
                    }
                }
            }
            return null;
        }

        public string GetCurrentBookFilename(string licenseName)
        {
            if (licenseDic.ContainsKey(licenseName))
            {
                return licenseDic[licenseName];
            }
            else
            {
                return null;
            }
        }

        public void ChangeBookName(string prevName, string newName)
        {
            BookData book = GetBook(prevName);
            book.Name = newName;
            string val = licenseDic[prevName];
            licenseDic.Remove(prevName);
            licenseDic.Add(newName, val);
        }

        public void UpdateDefaultBookPath(string fileName)
        {
            BookData book = BookData.Load(fileName);
            if (licenseDic.ContainsKey(book.Name))
            {
                for (int i = 0; i < defaultList.Count; i++)
                {
                    BookData cur = BookData.Load(defaultList[i]);
                    if (book.Name.Equals(cur.Name, StringComparison.OrdinalIgnoreCase))
                    {
                        defaultList[i] = fileName;
                        break;
                    }
                }
            }
        }

        public void Reset()
        {
            licenseDic.Clear();
            bookdata.Clear();
            defaultList.Clear();
            filenameList.Clear();
        }
    }
}
